/**
 * @file 简单字符串
 * @author snow-tyan (zziywang@163.com)
 * @brief {Life is too short to learn cpp.}
 * @version 0.1
 * @date 2021-11-11
 *
 * @copyright Copyright (c) 2021
 *
 * 05.替换空格
 * 50.第一个只出现一次的字符
 * 20.表示数值的字符串
 */

#include <iostream>
#include <queue>
#include <string>
#include <vector>
using namespace std;

class Solution
{
public:
    string replaceSpace(string s)
    {
        string res;
        for (char &ch : s) {
            if (ch == ' ') {
                res += "%20";
            } else {
                res += ch;
            }
        }
        return res;
    }
    // 50.
    char firstUniqChar(string s)
    {
        // 两次遍历字符串，第一次计数，第二次找cnt==1的第一个字符
#if 0
        vector<int> cnt(26, 0);
        for (char &ch : s){
            cnt[ch - 'a'] += 1;
        }
        for (char &ch : s){
            if (1 == cnt[ch - 'a']){
                return ch;
            }
        }
        return ' ';
#endif
        // 计数 + 队列 可以实现一遍扫描
        // 当队头弹出时，检查新队头的cnt是否大于1
        vector<int> cnt(26, 0);
        queue<char> q;
        for (char &ch : s) {
            cnt[ch - 'a'] += 1;
            if (q.empty() || ch != q.front()) {
                q.push(ch);
            } else {
                q.pop();
            }
            // 检查新队头是否cnt大于1
            while (!q.empty() && cnt[q.front() - 'a'] > 1) {
                q.pop();
            }
        }
        return q.empty() ? ' ' : q.front();
    }
    // 20.合法表示数值的字符串
    bool isNumber(string s)
    {
        // 模拟
        if (s.empty()) {
            return false;
        }
        int i = 0;
        // 开头有空格，略过
        while (s[i] == ' ') {
            ++i;
        }
        bool numeric = scanInterger(s, i);
        // 小数点
        if (s[i] == '.') {
            ++i;
            // 小数前后可以有数字，也可以没有
            numeric = scanUnsignedInterger(s, i) || numeric;
        }
        // 如果出现e或者E
        if (s[i] == 'e' || s[i] == 'E') {
            ++i;
            // e前面必须有数字，后面必须有整数
            numeric = numeric && scanInterger(s, i);
        }
        // 尾部空格，略过
        while (s[i] == ' ') {
            ++i;
        }
        return numeric && i == s.size();
    }

private:
    // 扫描整数部分
    bool scanInterger(string &s, int &i)
    {
        // 碰到符号位
        if (s[i] == '+' || s[i] == '-') {
            ++i;
        }
        return scanUnsignedInterger(s, i);
    }
    bool scanUnsignedInterger(string &s, int &i)
    {
        int pre = i;
        while (i != s.size() && s[i] >= '0' && s[i] <= '9') {
            ++i;
        }
        // i是否扫描到了数字？
        return i > pre;
    }
};

Solution solve = Solution();

void test05()
{
    string s = "We are happy.";
    cout << solve.replaceSpace(s) << endl;
}

void test20()
{
    // true
    cout << solve.isNumber("+100") << endl;
    cout << solve.isNumber("5e2") << endl;
    cout << solve.isNumber("-123") << endl;
    cout << solve.isNumber("3.14159") << endl;
    cout << solve.isNumber("-1E-16") << endl;
    cout << solve.isNumber("-1E+16") << endl;
    // false
    cout << solve.isNumber("12e") << endl;
    cout << solve.isNumber("1a3.14") << endl;
    cout << solve.isNumber("1.2.3") << endl;
    cout << solve.isNumber("+-5") << endl;
    cout << solve.isNumber("12e+5.4") << endl;
}

int main()
{
    // test05();
    test20();
    return 0;
}